package com.zhangjk.util.poi;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public class ImportExcelUtils {


    /**
     *
     * @param file 上传的excel对象   接收规范：
     *             1.单元格类型是数值类型的（带小数点的）用Double类型接收。
     *             2.单元格类型是常规或者文本的，都可以用String类型来接收。
     *             3.单元格类型是日期的，用用Date类型来接收。
     * @param obj  excel接收的对象（接收的实体） 对象规范：excel表头的顺序与该类属性的顺序保持一致，个数保持一致。
     * @return  直接强转  如： List<Test> testList=(List<Test>)ImportExcel.importData(file,obj);
     * @throws Exception
     */
    public static Object importData(MultipartFile file, Object obj) throws Exception {
        checkFile(file);
        Workbook wb = null;
        List<Object> HeroList = new ArrayList();
        //判断excel是2003或者 2007
        try {
            wb = new XSSFWorkbook(file.getInputStream());
        } catch (Exception ex) {
            wb = new HSSFWorkbook(new POIFSFileSystem(file.getInputStream()));
        }
        int hangh=0;
        int lieh=0;
        try {
            Class clazz = obj.getClass();  // 拿到该类
            Sheet sheet = wb.getSheetAt(0);//获取第一张表
            for (int i = 2; i < sheet.getLastRowNum()+1; i++){
                hangh=i+1;
                Object u1 =  clazz.newInstance();
                Row row = sheet.getRow(i);//获取索引为i的行，以2开始
                Field[] fs= u1.getClass().getDeclaredFields();
                for(int j=0;j<fs.length;j++){
                    lieh=j+1;
                    Field f = fs[j];
                    fs[j].setAccessible(true);
                    if (f.getGenericType().toString().equals("class java.lang.Double")){
                        f.set(u1,row.getCell(j).getNumericCellValue());
                    }else if(f.getGenericType().toString().equals("class java.lang.String")){
                        f.set(u1,getCellValue(row.getCell(j)));
                    }else if(f.getGenericType().toString().equals("class java.lang.Boolean")){
                        f.set(u1,row.getCell(j).getBooleanCellValue());
                    }else if(f.getGenericType().toString().equals("class java.util.Date")){
                        f.set(u1,row.getCell(j).getDateCellValue());
                    }else if(f.getGenericType().toString().equals("class java.lang.Integer")){
                        f.set(u1,Integer.parseInt(getCellValue(row.getCell(j))));
                    }else {
                        f.set(u1,row.getCell(j).getStringCellValue());
                    }
                }
                HeroList.add(u1);
            }
        }catch (Exception e){
           throw new PoiException("POE_IMPORTEXCEL_TYPEEXCEPTION","类型转换异常:第"+hangh+"行,第"+lieh+"列类型异常！！");
        }
        try {
            wb.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            wb.close();
        }
        return  HeroList;
    }

    public static   String getCellValue(Cell cell) {
        String cellValue = "";
        if (cell == null) {
            return cellValue;
        }
        // 判断数据的类型
        switch (cell.getCellTypeEnum()) {
            case NUMERIC: // 数字
                if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式
                    SimpleDateFormat sdf = null;
                    // 验证short值
                    if (cell.getCellStyle().getDataFormat() == 14) {
                        sdf = new SimpleDateFormat("yyyy/MM/dd");
                    } else if (cell.getCellStyle().getDataFormat() == 21) {
                        sdf = new SimpleDateFormat("HH:mm:ss");
                    } else if (cell.getCellStyle().getDataFormat() == 22) {
                        sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    } else {
                        throw new RuntimeException("日期格式错误!!!");
                    }
                    Date date = cell.getDateCellValue();
                    cellValue = sdf.format(date);
                } else if (cell.getCellStyle().getDataFormat() == 0) {//处理数值格式
                    cell.setCellType(CellType.STRING);
                    cellValue = String.valueOf(cell.getRichStringCellValue().getString());
                }
                break;
            case STRING: // 字符串
                cellValue = String.valueOf(cell.getStringCellValue());
                break;
            case BOOLEAN: // Boolean
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case FORMULA: // 公式
                cellValue = String.valueOf(cell.getCellFormula());
                break;
            case BLANK: // 空值
                cellValue = null;
                break;
            case ERROR: // 故障
                cellValue = "非法字符";
                break;
            default:
                cellValue = "未知类型";
                break;
        }
        return cellValue;
    }


    public static void checkFile(MultipartFile file) throws IOException{
        //判断文件是否存在
        if(null == file){
            log.error("文件不存在！");
            throw new FileNotFoundException("文件不存在！");
        }
        //获得文件名
        String fileName = file.getOriginalFilename();
        //判断文件是否是excel文件
        if(!fileName.endsWith("xls") && !fileName.endsWith("xlsx")){
            log.error(fileName + "不是excel文件");
            throw new IOException(fileName + "不是excel文件");
        }
    }
}
